#include <iostream>
#include <sys/socket.h>
#include <cstring>
#include <arpa/inet.h>
#include <unistd.h>
#include <json-c/json.h>
#include "stdShared.h"
#include <pthread.h>

using namespace std;

// 服务端口
#define SERVER_PORT 8080
// 缓冲区大小
#define USERINFO_SIZE 20
#define BUFFER_SIZE 128

// 定义用户信息结构体
struct userInfo
{
    int type; // 1：注册  2：登录
    char name[USERINFO_SIZE];
    char passwd[USERINFO_SIZE];
};

void *thread_func(void *arg)
{
    // 线程分离
    pthread_detach(pthread_self());

    // 参数转换
    int connfd = *(int *)arg;

    // 接收缓冲区
    int readBytes = 0;
    char readBuffer[BUFFER_SIZE];

    while (1)
    {
        memset(readBuffer, 0, sizeof(readBuffer));
        readBytes = read(connfd, readBuffer, sizeof(readBuffer));

        if (readBytes < 0)
        {
            perror("read error");
            break;
        }
        else if (readBytes == 0)
        {
            cout << "客户端下线" << endl;
            break;
        }
        cout << "readBytes:" << readBytes << ", readBuffer:" << readBuffer << endl;

        // 1、将json字符串解析成json对象
        json_object *jsonObj = json_tokener_parse(readBuffer);

        // 2、根据key得到value
    #if 0
        json_object *typeVal = json_object_object_get(jsonObj, "type");
        cout << "type:" << json_object_get_int(typeVal) << endl;
    #else
        int type = json_object_get_int(json_object_object_get(jsonObj, "type"));
        const char *name = json_object_get_string(json_object_object_get(jsonObj, "name"));
        const char *passwd = json_object_get_string(json_object_object_get(jsonObj, "passwd"));
        const char *musicName = json_object_get_string(json_object_object_get(jsonObj, "musicname"));
        
        if (type == REGISTER)
        {
            cout << "注册..." << endl;
            cout << "name:" << name << endl;
            cout << "passwd:" << passwd << endl;
        }
        else if (type == LOGIN)
        {
            cout << "登录..." << endl;
            cout << "name:" << name << endl;
            cout << "passwd:" << passwd << endl;
        }
        else if (type == DOWNLOAD_MUSIC)
        {
            cout << "下载音乐..." << endl;
            cout << "musicName:" << musicName << endl;
        }

        // 释放json对象
        json_object_put(jsonObj);
    #endif
    }

    // 回收文件描述符
    close(connfd); // 文件描述符的尽头是1024，资源是有限的，所以要回收

    // 线程退出
    pthread_exit(NULL);
} 

int main()
{
    // 创建socket套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        perror("socket error");
        exit(-1);
    }
    cout << "sockfd:" << sockfd << endl;

    // 设置端口复用
    int optVal = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));

    // 绑定IP和端口信息
    struct sockaddr_in localAddress;

    // 清空结构体的脏数据
    memset(&localAddress, 0, sizeof(localAddress));

    // 地址族是IPV4
    localAddress.sin_family = AF_INET;
    localAddress.sin_port = htons(SERVER_PORT);

    // 设置全通规则
    localAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    // 绑定
    bind(sockfd, reinterpret_cast<const struct sockaddr *>(&localAddress), sizeof(localAddress));

    // 设置监听
    listen(sockfd, 10); // 迎宾人员
    cout << "服务器阻塞等待客户端接入..." << endl;

    while (1)
    {
        // 通信句柄
        // 阻塞函数
        int connfd = accept(sockfd, NULL, NULL); // 招待人员
        cout << "有人跟我连接了..." << connfd << endl;

        // 读取客户端发来的信息
        // int readBytes = 0;
        // char readBuffer[BUFFER_SIZE];
        // userInfo clientInfo;
        // 清空缓冲区
        // memset(readBuffer, 0, sizeof(readBuffer));
        // memset(&clientInfo, 0, sizeof(clientInfo));       
    #if 0 
        while (1)
        {
            // readBytes = read(connfd, readBuffer, sizeof(readBuffer));
            // cout << "readBytes:" << readBytes << ", readBuffer:" << readBuffer << endl;

            // // 将客户端发来的信息转成大写
            // for (int i = 0; i < readBytes; i++)
            // {
            //     readBuffer[i] = toupper(readBuffer[i]);
            // }

            // // 写回给客户端
            // write(connfd, readBuffer, readBytes);

            memset(&info, 0, sizeof(info));
            readBytes = read(connfd, &clientInfo, sizeof(clientInfo));
            cout << "type:" << clientInfo.type << ", name:" << clientInfo.name << ", passwd:" << clientInfo.passwd << endl;
        }
    #endif

        pthread_t tid;
        int ret = pthread_create(&tid, NULL, thread_func, &connfd);
        if (ret != 0)
        {
            perror("thread creat error");
            exit(-1);
        }

        sleep(1);
    }

    return 0;
}